﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace SQLFileComparer
{
    class ForwardProcessor : MainAction
    {
        private void WriteName(string name, bool writeLngth = true)
        {
            if (writeLngth)
            {
                var length = name.Length;
                Debug.Assert(length < 255);
                DataHolder.WriteByte((Byte)(length & 255));
            }

            var bname = Encoding.Default.GetBytes(name.ToLower());
            WriteBytes(bname, false);
        }

        private void WriteInt(int value)
        {
            WriteBytes(BitConverter.GetBytes(value), false);
        }

        private void ReadFiles(string path, string filter, int days)
        {
            var files = new List<FileInfo>();

            var currentDate = DateTime.Now;
            foreach (var file in Directory.GetFiles(path, filter, SearchOption.AllDirectories))
            {
                var finfo = new FileInfo(file);
                if (days != -1)
                {
                    if ((finfo.LastWriteTime - currentDate).TotalDays <= days)
                        files.Add(finfo);
                }
                else
                    files.Add(finfo);
            }

            files.Sort((file1, file2) => -DateTime.Compare(file1.LastWriteTime, file2.LastWriteTime));

            foreach (var file in files)
            {
                var bytes = File.ReadAllBytes(file.FullName);
                WriteName(file.FullName.Remove(0, path.Length));
                WriteInt(bytes.Length);
                WriteBytes(bytes, false);
            }
        }

        private void Compress()
        {
            Byte[] outArray;
            using (var outStream = new MemoryStream())
            using (var compress = new DeflateStream(outStream, CompressionMode.Compress))
            {
                var buff = DataHolder.ToArray();
                compress.Write(buff, 0, buff.Length);
                outArray = outStream.ToArray();
            }

            WriteBytes(outArray);
        }

        private void Cript()
        {
            var key = Convert.FromBase64String(Params.Key);
            var bytes = DataHolder.ToArray();
            for (var i = 0; i < bytes.Length; i++)
                bytes[i] ^= key[i % 1024];

            WriteBytes(Encoding.Default.GetBytes(Convert.ToBase64String(bytes)));
        }

        public int Process(string path, string filter, int days = -1)
        {
            if (!Directory.Exists(path))
                return CDirectoryNotFound;

            ReadFiles(path, filter, days);

            Compress();

            Cript();

            return COk;
        }

        public ForwardProcessor(ActionParams actionParams)
            : base(actionParams)
        {
        }
    }
}
